package util

func NewIterator[T any](hasNext func() bool, next func() T) Iterator[T] {
	return &iterator[T]{
		hasNext: hasNext,
		next:    next,
	}
}

func FromSlice[T any](slices []T) Iterator[T] {
	index := 0
	length := len(slices)

	hasNext := func() bool {
		return index < length
	}
	next := func() T {
		current := slices[index]
		index = index + 1
		return current
	}

	return NewIterator(hasNext, next)
}

type Iterator[T any] interface {
	HasNext() bool
	Next() T
	ToSlice() []T
}

type iterator[T any] struct {
	hasNext func() bool
	next    func() T
}

func (i *iterator[T]) HasNext() bool {
	return i.hasNext()
}
func (i *iterator[T]) Next() T {
	return i.next()
}
func (i *iterator[T]) ToSlice() []T {
	result := []T{}

	for i.HasNext() {
		result = append(result, i.Next())
	}

	return result
}
